package initData

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/redis/go-redis/v9"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var (
	DB  *gorm.DB         // 全局数据库连接
	RDB *redis.Client    // 全局 Redis 连接
	Ctx = context.TODO() // 公共上下文
)

// 数据库连接配置
const (
	dbUser     = "lml"
	dbPassword = "LMLlml062424"
	dbHost     = "rm-cn-m1e4ah63c0002uso.rwlb.rds.aliyuncs.com"
	dbPort     = "3306"
	dbName     = "l-wd"
)

// 定义数据库模型（根据实际表结构）
type Message struct {
	ID          int64     `gorm:"primaryKey;column:id"`
	TemplateID  *int64    `gorm:"column:template_id"`
	Title       string    `gorm:"column:title"`
	Content     string    `gorm:"column:content;type:text"`
	TypeID      *int64    `gorm:"column:type_id"`
	Format      string    `gorm:"column:format"`
	SendType    string    `gorm:"column:send_type"`
	SendTime    time.Time `gorm:"column:send_time"`
	CreatedTime time.Time `gorm:"column:created_time"`
}

func (Message) TableName() string {
	return "l_message"
}

type UserMessage struct {
	ID          int64     `gorm:"primaryKey;column:id"`
	UserID      string    `gorm:"column:user_id;type:varchar(255)"`
	MessageID   int64     `gorm:"column:message_id"`
	ReadStatus  int       `gorm:"column:read_status"`
	Deleted     int       `gorm:"column:deleted"`
	ReceiveTime time.Time `gorm:"column:receive_time"`
	AcceptID    *string   `gorm:"column:accept_id"`
}

func (UserMessage) TableName() string {
	return "l_user_message"
}

func SyncRedisData() {
	var err error
	// 初始化数据库连接
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
		dbUser, dbPassword, dbHost, dbPort, dbName)
	DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		log.Fatalf("数据库连接失败: %v", err)
	}

	log.Println("✅ 数据库连接成功: ", DB)

	// 初始化Redis连接
	rdb := redis.NewClient(&redis.Options{
		Addr:     "47.120.60.61:6379",
		Password: "123456",
		DB:       0,
	})

	ctx := context.Background()
	if _, err := rdb.Ping(ctx).Result(); err != nil {
		log.Fatalf("Redis连接失败: %v", err)
	} else {
		log.Println("✅ Redis连接成功")
	}

	// 💡 清除Redis中旧的缓存数据
	if err := clearRedisKeys(ctx, rdb); err != nil {
		log.Fatalf("清理Redis缓存失败: %v", err)
	}

	// 同步消息数据到Redis Hash
	if err := syncMessagesToRedis(ctx, DB, rdb); err != nil {
		log.Fatalf("同步消息失败: %v", err)
	}

	// 同步用户消息到Redis List
	if err := syncUserMessagesToRedis(ctx, DB, rdb); err != nil {
		log.Fatalf("同步用户消息失败: %v", err)
	}

	log.Println("数据同步完成!")

}

// 同步l_message表到Redis Hash
func syncMessagesToRedis(ctx context.Context, db *gorm.DB, rdb *redis.Client) error {
	var messages []Message
	result := db.Find(&messages)
	if result.Error != nil {
		return fmt.Errorf("查询消息失败: %w", result.Error)
	}

	total := len(messages)
	log.Printf("开始同步 %d 条消息到Redis Hash...", total)

	// 使用Pipeline批量操作
	batchSize := 1000
	for i := 0; i < total; i += batchSize {
		end := i + batchSize
		if end > total {
			end = total
		}

		batch := messages[i:end]
		pipe := rdb.Pipeline()

		for _, msg := range batch {
			key := fmt.Sprintf("message:%d", msg.ID)

			// 创建Hash字段
			fields := map[string]interface{}{
				"id":           msg.ID,
				"title":        msg.Title,
				"content":      msg.Content,
				"send_time":    msg.SendTime.Format(time.RFC3339),
				"created_time": msg.CreatedTime.Format(time.RFC3339),
			}

			// 添加可选字段
			if msg.TemplateID != nil {
				fields["template_id"] = *msg.TemplateID
			}
			if msg.TypeID != nil {
				fields["type_id"] = *msg.TypeID
			}
			if msg.Format != "" {
				fields["format"] = msg.Format
			}
			if msg.SendType != "" {
				fields["send_type"] = msg.SendType
			}

			pipe.HSet(ctx, key, fields)
			pipe.Expire(ctx, key, 24*time.Hour)
		}

		if _, err := pipe.Exec(ctx); err != nil {
			return fmt.Errorf("执行pipeline失败: %w", err)
		}

		log.Printf("已处理 %d/%d 条消息", end, total)
	}

	log.Printf("成功同步 %d 条消息到Redis Hash", total)
	return nil
}

// 同步l_user_message表到Redis List + Hash
func syncUserMessagesToRedis(ctx context.Context, db *gorm.DB, rdb *redis.Client) error {
	// 查询所有用户ID（只包含未删除的消息）
	var userIDs []string
	if err := db.Model(&UserMessage{}).
		Where("deleted = 0").
		Distinct().
		Pluck("accept_id", &userIDs).Error; err != nil {
		return fmt.Errorf("查询用户ID失败: %w", err)
	}

	totalUsers := len(userIDs)
	log.Printf("开始同步 %d 个用户的消息列表到Redis...", totalUsers)

	batchSize := 500
	for i := 0; i < totalUsers; i += batchSize {
		end := i + batchSize
		if end > totalUsers {
			end = totalUsers
		}

		batch := userIDs[i:end]
		pipe := rdb.Pipeline()

		log.Println("批量处理用户ID:", batch)

		for _, userID := range batch {
			// 查询该用户的所有消息（包含字段）
			var userMsgs []UserMessage
			if err := db.Model(&UserMessage{}).
				Where("accept_id = ? AND deleted = 0", userID).
				Order("receive_time DESC").
				Find(&userMsgs).Error; err != nil {
				return fmt.Errorf("查询用户消息失败: %w", err)
			}

			listKey := fmt.Sprintf("user_messages:%s", userID)
			log.Println("listKey: ", listKey)
			pipe.Del(ctx, listKey) // 删除旧的 List

			for _, msg := range userMsgs {
				// 添加到 List 列表
				pipe.RPush(ctx, listKey, msg.MessageID)

				// 组装每条 user_message 的 Hash 数据
				hashKey := fmt.Sprintf("user_message:%s:%d", userID, msg.MessageID)
				fields := map[string]interface{}{
					"id":           msg.ID,
					"user_id":      msg.UserID,
					"message_id":   msg.MessageID,
					"read_status":  msg.ReadStatus,
					"deleted":      msg.Deleted,
					"receive_time": msg.ReceiveTime.Format(time.RFC3339),
				}
				if msg.AcceptID != nil {
					fields["accept_id"] = *msg.AcceptID
				}

				pipe.HSet(ctx, hashKey, fields)
				pipe.Expire(ctx, hashKey, 24*time.Hour)
			}

			pipe.Expire(ctx, listKey, 24*time.Hour)
		}

		if _, err := pipe.Exec(ctx); err != nil {
			return fmt.Errorf("执行pipeline失败: %w", err)
		}

		log.Printf("已处理 %d/%d 个用户", end, totalUsers)
	}

	log.Printf("成功同步 %d 个用户的消息列表到Redis", totalUsers)
	return nil
}

// 清理缓存key数据
func clearRedisKeys(ctx context.Context, rdb *redis.Client) error {
	// 匹配相关的 key
	patterns := []string{"message:*", "user_messages:*", "user_message:*"}

	for _, pattern := range patterns {
		var cursor uint64
		for {
			keys, nextCursor, err := rdb.Scan(ctx, cursor, pattern, 1000).Result()
			if err != nil {
				return fmt.Errorf("扫描 key [%s] 失败: %w", pattern, err)
			}

			if len(keys) > 0 {
				if err := rdb.Del(ctx, keys...).Err(); err != nil {
					return fmt.Errorf("删除 key [%s] 失败: %w", pattern, err)
				}
				log.Printf("已删除匹配模式 %s 的 %d 个 key", pattern, len(keys))
			}

			if nextCursor == 0 {
				break
			}
			cursor = nextCursor
		}
	}

	log.Println("✅ Redis 缓存清理完成")
	return nil
}
